#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
意图分类服务

快速判断用户输入是"可执行指令"还是"对话问答"
使用规则+LLM混合策略，优先快速规则判断，不确定时才使用LLM
"""

import re
from typing import Tuple

# 处理相对导入和直接运行的兼容性
try:
    from .llm_client import LLMClient
except ImportError:
    from llm_client import LLMClient


class IntentClassifier:
    """
    意图分类器
    将用户输入分类为"指令"或"对话"
    """
    
    def __init__(self):
        """初始化意图分类器"""
        self.llm_client = LLMClient()
        
        # 可执行指令关键词（按类别组织）
        self.command_keywords = {
            'music': ['播放', '暂停', '停止', '下一首', '上一首', '音乐', '歌曲', '唱'],
            'alarm': ['闹钟', '提醒', '定时', '叫我', '叫醒'],
            'file': ['文件', '创建', '删除', '保存', '新建'],
            'system': ['打开', '关闭', '启动', '退出'],
            'map': ['天气', '气温', '温度', '下雨', '搜索', '查找', '附近', '哪里有', 
                    '怎么去', '怎么走', '路线', '导航', '到', '地址', '在哪', '位置']
        }
        
        # 对话特征词（问候、询问、闲聊等）
        # 注意：不要包含"帮我"，因为"帮我查天气"等是指令而非对话
        self.conversation_keywords = [
            '你好', '您好', '嗨', 'hi', 'hello',
            '怎么样', '如何', '是什么', '为什么', '什么是',
            '讲个', '聊聊', '告诉我', '解释', '说说',
            '帮我写', '写一个', '写一篇', '生成',  # 保留"帮我写"因为是内容生成
            '翻译', '计算', '回答', '介绍'
        ]
        
        # 问句标识
        self.question_patterns = [
            r'.*吗[？?]?$',  # 以"吗"结尾
            r'.*呢[？?]?$',  # 以"呢"结尾
            r'^为什么',
            r'^怎么',
            r'^如何',
            r'^什么',
            r'^哪',
            r'[？?]',  # 包含问号
        ]
    
    def quick_classify(self, text: str) -> Tuple[str, float]:
        """
        快速分类：使用规则进行快速判断
        
        Args:
            text: 用户输入文本
            
        Returns:
            (intent_type, confidence)
            intent_type: 'command' | 'conversation' | 'unknown'
            confidence: 置信度 0.0-1.0
        """
        # 规则1：明确的指令关键词
        for category, keywords in self.command_keywords.items():
            if any(kw in text for kw in keywords):
                # 进一步判断：如果同时包含"播放"和"写"/"生成"，可能是内容生成
                if '播放' in text and ('写' in text or '生成' in text):
                    return ('conversation', 0.6)
                
                # 特殊处理：地图相关的指令即使包含"帮我"也应该识别为指令
                # 因为"帮我查天气"、"帮我搜索"等都是明确的操作请求
                if category == 'map':
                    print(f"🎯 [快速分类] 匹配地图指令关键词: {category}")
                    return ('command', 0.9)  # 更高置信度
                
                print(f"🎯 [快速分类] 匹配指令关键词: {category}")
                return ('command', 0.85)
        
        # 规则2：明确的对话特征
        for keyword in self.conversation_keywords:
            if keyword in text:
                print(f"🎯 [快速分类] 匹配对话关键词: {keyword}")
                return ('conversation', 0.85)
        
        # 规则3：问句特征
        for pattern in self.question_patterns:
            if re.search(pattern, text):
                print(f"🎯 [快速分类] 匹配问句模式")
                return ('conversation', 0.8)
        
        # 规则4：短文本（<5字）且无标点，可能是简单问候或指令
        if len(text) < 5 and not any(p in text for p in '，。！？,.!?'):
            # 如果是常见问候语
            if text in ['嗨', '哈喽', '在吗', '在不在']:
                print(f"🎯 [快速分类] 短文本问候")
                return ('conversation', 0.9)
            # 否则不确定
            print(f"🎯 [快速分类] 短文本不确定")
            return ('unknown', 0.3)
        
        # 规则5：长文本（>30字）通常是对话或内容生成请求
        if len(text) > 30:
            # 如果包含"写"、"生成"、"帮我"等词，很可能是内容生成请求
            content_gen_keywords = ['写', '生成', '帮我', '创作', '编写']
            if any(kw in text for kw in content_gen_keywords):
                print(f"🎯 [快速分类] 长文本内容生成请求")
                return ('conversation', 0.75)
        
        # 无法快速判断
        print(f"🎯 [快速分类] 无法确定，需要LLM分类")
        return ('unknown', 0.3)
    
    def llm_classify(self, text: str) -> Tuple[str, float]:
        """
        使用LLM进行精确分类（用于不确定的情况）
        
        Args:
            text: 用户输入文本
            
        Returns:
            (intent_type, confidence)
        """
        try:
            system_prompt = """你是一个意图分类专家。请判断用户输入是"可执行指令"还是"对话问答"。

**可执行指令 (command)**：
- 要求系统执行某个操作：播放音乐、打开应用、设置闹钟、创建文件、查询天气、搜索地点、规划路线等
- 特征：有明确的动作词（播放、打开、设置、创建、查询、搜索、导航等）
- 地图相关：查询天气、搜索地点、规划路线、查地址等

**对话问答 (conversation)**：
- 聊天、问答、内容生成、知识查询等
- 特征：问候、询问、讲述、"写一篇"、"告诉我"等

注意：
- "查询北京天气" → command（可执行的天气查询）
- "搜索附近的咖啡馆" → command（可执行的地点搜索）
- "从A到B怎么走" → command（可执行的路线规划）

只需返回一个单词：command 或 conversation"""
            
            user_prompt = f"""请分类以下文本：

"{text}"

返回：command 或 conversation"""
            
            print(f"🤔 [LLM分类] 开始调用LLM...")
            
            response = self.llm_client.chat(
                user_input=user_prompt,
                system_prompt=system_prompt,
                max_tokens=10,
                temperature=0.1  # 低温度，提高准确性
            )
            
            if not response:
                print(f"⚠️ [LLM分类] LLM调用失败，默认为对话")
                return ('conversation', 0.5)
            
            intent = response.strip().lower()
            
            if 'command' in intent:
                print(f"🎯 [LLM分类] 判定为指令")
                return ('command', 0.8)
            elif 'conversation' in intent:
                print(f"🎯 [LLM分类] 判定为对话")
                return ('conversation', 0.8)
            else:
                print(f"⚠️ [LLM分类] 无法识别响应: {intent}，默认为对话")
                return ('conversation', 0.5)
                
        except Exception as e:
            print(f"❌ [LLM分类] 异常: {e}，默认为对话")
            return ('conversation', 0.5)
    
    def classify(self, text: str) -> str:
        """
        综合分类策略
        
        Args:
            text: 用户输入文本
            
        Returns:
            'command' | 'conversation'
        """
        print(f"")
        print(f"=" * 60)
        print(f"🔍 [意图分类] 开始分类: {text[:50]}{'...' if len(text) > 50 else ''}")
        print(f"=" * 60)
        
        # 先快速分类
        intent_type, confidence = self.quick_classify(text)
        
        # 如果置信度高（>0.7），直接返回
        if confidence >= 0.7:
            print(f"✅ [意图分类] 快速分类成功: {intent_type} (置信度: {confidence:.2f})")
            print(f"=" * 60)
            return intent_type
        
        # 否则用LLM精确分类
        print(f"🔄 [意图分类] 置信度较低 ({confidence:.2f})，使用LLM精确分类...")
        intent_type, confidence = self.llm_classify(text)
        print(f"✅ [意图分类] LLM分类完成: {intent_type} (置信度: {confidence:.2f})")
        print(f"=" * 60)
        
        return intent_type
    
    def is_command(self, text: str) -> bool:
        """
        判断是否为可执行指令
        
        Args:
            text: 用户输入文本
            
        Returns:
            True: 是指令, False: 是对话
        """
        return self.classify(text) == 'command'


def main():
    """测试函数"""
    classifier = IntentClassifier()
    
    # 测试用例
    test_cases = [
        # 明确的指令
        "播放周杰伦的稻香",
        "打开记事本",
        "设置明天早上8点的闹钟",
        "暂停音乐",
        
        # 地图指令
        "查询北京的天气",
        "帮我查一下明天的天气",  # 新增：测试"帮我"开头的地图指令
        "搜索附近的星巴克",
        "从天安门到鸟巢怎么走",
        "天安门的地址",
        
        # 明确的对话
        "你好",
        "今天天气怎么样",  # 注意：这个可能被误判，需要看完整上下文
        "为什么天空是蓝色的",
        "帮我写一篇关于春天的作文",
        "翻译：hello world",
        
        # 不确定的情况
        "讲个笑话",
        "你会什么",
        "再来一首",
    ]
    
    print("🧪 开始测试意图分类...")
    print("=" * 80)
    
    for i, text in enumerate(test_cases, 1):
        print(f"\n测试 {i}: {text}")
        intent = classifier.classify(text)
        print(f"结果: {intent}")
        print("-" * 80)


if __name__ == "__main__":
    main()

